home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet internetowy / Przegladarki internetowe / Mozilla Seamonkey 1.0.5 pl / seamonkey-1.0.5.pl-PL.win32.installer.exe / MAIL.XPI / bin / chrome / messenger.jar / content / messenger / messageWindow.js < prev    next >
Encoding:
Text File  |  2006-01-20  |  28.6 KB  |  1,053 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  2.  * ***** BEGIN LICENSE BLOCK *****
  3.  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  4.  *
  5.  * The contents of this file are subject to the Mozilla Public License Version
  6.  * 1.1 (the "License"); you may not use this file except in compliance with
  7.  * the License. You may obtain a copy of the License at
  8.  * http://www.mozilla.org/MPL/
  9.  *
  10.  * Software distributed under the License is distributed on an "AS IS" basis,
  11.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  12.  * for the specific language governing rights and limitations under the
  13.  * License.
  14.  *
  15.  * The Original Code is Mozilla Communicator client code, released
  16.  * March 31, 1998.
  17.  *
  18.  * The Initial Developer of the Original Code is
  19.  * Netscape Communications Corporation.
  20.  * Portions created by the Initial Developer are Copyright (C) 1998-1999
  21.  * the Initial Developer. All Rights Reserved.
  22.  *
  23.  * Contributor(s):
  24.  *
  25.  * Alternatively, the contents of this file may be used under the terms of
  26.  * either of the GNU General Public License Version 2 or later (the "GPL"),
  27.  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  28.  * in which case the provisions of the GPL or the LGPL are applicable instead
  29.  * of those above. If you wish to allow use of your version of this file only
  30.  * under the terms of either the GPL or the LGPL, and not to allow others to
  31.  * use your version of this file under the terms of the MPL, indicate your
  32.  * decision by deleting the provisions above and replace them with the notice
  33.  * and other provisions required by the GPL or the LGPL. If you do not delete
  34.  * the provisions above, a recipient may use your version of this file under
  35.  * the terms of any one of the MPL, the GPL or the LGPL.
  36.  *
  37.  * ***** END LICENSE BLOCK ***** */
  38.  
  39. /* This is where functions related to the standalone message window are kept */
  40.  
  41. // from MailNewsTypes.h
  42. const nsMsgKey_None = 0xFFFFFFFF;
  43. const nsMsgViewIndex_None = 0xFFFFFFFF;
  44.  
  45. /* globals for a particular window */
  46.  
  47. var compositeDataSourceContractID        = datasourceContractIDPrefix + "composite-datasource";
  48.  
  49. var gCompositeDataSource;
  50. var gCurrentMessageUri;
  51. var gCurrentFolderUri;
  52. var gThreadPaneCommandUpdater = null;
  53. var gCurrentMessageIsDeleted = false;
  54. var gNextMessageViewIndexAfterDelete = -2;
  55. var gCurrentFolderToRerootForStandAlone;
  56. var gRerootOnFolderLoadForStandAlone = false;
  57. var gNextMessageAfterLoad = null;
  58.  
  59. // the folderListener object
  60. var folderListener = {
  61.   OnItemAdded: function(parentItem, item) {},
  62.  
  63.   OnItemRemoved: function(parentItem, item) {
  64.     if (parentItem.Value != gCurrentFolderUri)
  65.       return;
  66.  
  67.     if (item instanceof Components.interfaces.nsIMsgDBHdr &&
  68.         extractMsgKeyFromURI() == item.messageKey)
  69.       gCurrentMessageIsDeleted = true;
  70.   },
  71.  
  72.   OnItemPropertyChanged: function(item, property, oldValue, newValue) {},
  73.   OnItemIntPropertyChanged: function(item, property, oldValue, newValue) { 
  74.     if (item.Value == gCurrentFolderUri) {
  75.       if (property.toString() == "TotalMessages" || property.toString() == "TotalUnreadMessages") {
  76.         UpdateStandAloneMessageCounts();
  77.       }      
  78.     }
  79.   },
  80.   OnItemBoolPropertyChanged: function(item, property, oldValue, newValue) {},
  81.   OnItemUnicharPropertyChanged: function(item, property, oldValue, newValue){},
  82.   OnItemPropertyFlagChanged: function(item, property, oldFlag, newFlag) {},
  83.  
  84.   OnItemEvent: function(folder, event) {
  85.     var eventType = event.toString();
  86.  
  87.     if (eventType == "DeleteOrMoveMsgCompleted")
  88.       HandleDeleteOrMoveMsgCompleted(folder);
  89.     else if (eventType == "DeleteOrMoveMsgFailed")
  90.       HandleDeleteOrMoveMsgFailed(folder);
  91.     else if (eventType == "FolderLoaded") {
  92.       if (folder) {
  93.         var uri = folder.URI;
  94.         if (uri == gCurrentFolderToRerootForStandAlone) {
  95.           gCurrentFolderToRerootForStandAlone = null;
  96.           var msgFolder = folder.QueryInterface(Components.interfaces.nsIMsgFolder);
  97.           if (msgFolder) {
  98.             msgFolder.endFolderLoading();
  99.             if (gRerootOnFolderLoadForStandAlone) {
  100.               RerootFolderForStandAlone(uri);
  101.             }
  102.           }   
  103.         }
  104.       }
  105.     }
  106.     else if (eventType == "JunkStatusChanged") {
  107.       HandleJunkStatusChanged(folder);
  108.     }
  109.   }   
  110. }
  111.  
  112. var messagepaneObserver = {
  113.  
  114.   canHandleMultipleItems: false,
  115.  
  116.   onDrop: function (aEvent, aData, aDragSession)
  117.   {
  118.     var sourceUri = aData.data; 
  119.     if (sourceUri != gCurrentMessageUri)
  120.     {
  121.       SelectFolder(GetMsgHdrFromUri(sourceUri).folder.URI);
  122.       SelectMessage(sourceUri);
  123.     }
  124.   },
  125.  
  126.   onDragOver: function (aEvent, aFlavour, aDragSession)
  127.   {
  128.     var messagepanebox = document.getElementById("messagepanebox");
  129.     messagepanebox.setAttribute("dragover", "true");
  130.   },
  131.  
  132.   onDragExit: function (aEvent, aDragSession)
  133.   {
  134.     var messagepanebox = document.getElementById("messagepanebox");
  135.     messagepanebox.removeAttribute("dragover");
  136.   },
  137.  
  138.   canDrop: function(aEvent, aDragSession)  //allow drop from mail:3pane window only - 4xp
  139.   {
  140.     var doc = aDragSession.sourceNode.ownerDocument;
  141.     var elem = doc.getElementById("messengerWindow");
  142.     return (elem && (elem.getAttribute("windowtype") == "mail:3pane"));
  143.   },
  144.   
  145.   getSupportedFlavours: function ()
  146.   {
  147.     var flavourSet = new FlavourSet();
  148.     flavourSet.appendFlavour("text/x-moz-message");
  149.     return flavourSet;
  150.   }
  151. };
  152.  
  153. function nsMsgDBViewCommandUpdater()
  154. {}
  155.  
  156. function UpdateStandAloneMessageCounts()
  157. {
  158.   // hook for extra toolbar items
  159.   var observerService = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);
  160.   observerService.notifyObservers(window, "mail:updateStandAloneMessageCounts", "");
  161. }
  162.  
  163. nsMsgDBViewCommandUpdater.prototype = 
  164. {
  165.   updateCommandStatus : function()
  166.     {
  167.       // the back end is smart and is only telling us to update command status
  168.       // when the # of items in the selection has actually changed.
  169.       UpdateMailToolbar("dbview, std alone window");
  170.     },
  171.  
  172.   displayMessageChanged : function(aFolder, aSubject, aKeywords)
  173.   {
  174.     setTitleFromFolder(aFolder, aSubject);
  175.     ClearPendingReadTimer(); // we are loading / selecting a new message so kill the mark as read timer for the currently viewed message
  176.     gCurrentMessageUri = gDBView.URIForFirstSelectedMessage;
  177.     UpdateStandAloneMessageCounts();
  178.     SetKeywords(aKeywords);
  179.     goUpdateCommand("button_junk");
  180.   },
  181.  
  182.   updateNextMessageAfterDelete : function()
  183.   {
  184.     SetNextMessageAfterDelete();
  185.   },
  186.  
  187.   QueryInterface : function(iid)
  188.   {
  189.     if (iid.equals(Components.interfaces.nsIMsgDBViewCommandUpdater) ||
  190.         iid.equals(Components.interfaces.nsISupports))
  191.       return this;
  192.       
  193.     throw Components.results.NS_NOINTERFACE;
  194.   }
  195. }
  196.  
  197. function HandleDeleteOrMoveMsgCompleted(folder)
  198. {
  199.     var folderResource = folder.QueryInterface(Components.interfaces.nsIRDFResource);
  200.     if (!folderResource)
  201.         return;
  202.  
  203.     if ((folderResource.Value == gCurrentFolderUri) && gCurrentMessageIsDeleted)
  204.     {
  205.     gDBView.onDeleteCompleted(true);
  206.     gCurrentMessageIsDeleted = false;
  207.     if (gNextMessageViewIndexAfterDelete != nsMsgViewIndex_None) 
  208.     {
  209.       var nextMstKey = gDBView.getKeyAt(gNextMessageViewIndexAfterDelete);
  210.       if (nextMstKey != nsMsgKey_None) {
  211.         LoadMessageByViewIndex(gNextMessageViewIndexAfterDelete);
  212.       }
  213.       else {
  214.         window.close();
  215.       }
  216.     }
  217.     else
  218.     {
  219.       // close the stand alone window because there are no more messages in the folder
  220.       window.close();
  221.     }
  222.     }
  223. }
  224.  
  225. function HandleDeleteOrMoveMsgFailed(folder)
  226. {
  227.   var folderResource = folder.QueryInterface(Components.interfaces.nsIRDFResource);
  228.   if (!folderResource)
  229.      return;
  230.  
  231.   gDBView.onDeleteCompleted(false);
  232.   if ((folderResource.Value == gCurrentFolderUri) && gCurrentMessageIsDeleted)
  233.     gCurrentMessageIsDeleted = false;
  234. }
  235.  
  236. function IsCurrentLoadedFolder(folder)
  237. {
  238.   var folderResource = folder.QueryInterface(Components.interfaces.nsIRDFResource);
  239.   if (!folderResource)
  240.      return false;
  241.  
  242.   return (folderResource.Value == gCurrentFolderUri);
  243. }
  244.  
  245. function OnLoadMessageWindow()
  246. {
  247.   AddMailOfflineObserver();
  248.     CreateMailWindowGlobals();
  249.     CreateMessageWindowGlobals();
  250.   AddToolBarPrefListener();
  251.   ShowHideToolBarButtons()
  252.     verifyAccounts(null);
  253.  
  254.     InitMsgWindow();
  255.  
  256.     messenger.SetWindow(window, msgWindow);
  257.     InitializeDataSources();
  258.     // FIX ME - later we will be able to use onload from the overlay
  259.     OnLoadMsgHeaderPane();
  260.  
  261.   try {
  262.     var nsIFolderListener = Components.interfaces.nsIFolderListener;
  263.     var notifyFlags = nsIFolderListener.removed | nsIFolderListener.event | nsIFolderListener.intPropertyChanged;
  264.     mailSession.AddFolderListener(folderListener, notifyFlags);
  265.   } catch (ex) {
  266.     dump("Error adding to session: " +ex + "\n");
  267.   }
  268.  
  269.   var originalView = null;
  270.   var folder = null;
  271.   var messageUri;
  272.   var loadCustomMessage = false;       //set to true when either loading a message/rfc822 attachment or a .eml file
  273.   if (window.arguments)
  274.   {
  275.     if (window.arguments[0])
  276.     {
  277.       try
  278.       {
  279.         messageUri = window.arguments[0];
  280.         if (messageUri instanceof Components.interfaces.nsIURI)
  281.         {
  282.           loadCustomMessage = /type=application\/x-message-display/.test(messageUri.spec);
  283.           gCurrentMessageUri = messageUri.spec;
  284.           if (messageUri instanceof Components.interfaces.nsIMsgMailNewsUrl)
  285.             folder = messageUri.folder;
  286.         }
  287.       } 
  288.       catch(ex) 
  289.       {
  290.         folder = null;
  291.         dump("## ex=" + ex + "\n");
  292.       }
  293.  
  294.       if (!gCurrentMessageUri)
  295.         gCurrentMessageUri = window.arguments[0];
  296.     }
  297.     else
  298.       gCurrentMessageUri = null;
  299.  
  300.     if (window.arguments[1])
  301.       gCurrentFolderUri = window.arguments[1];
  302.     else
  303.       gCurrentFolderUri = folder ? folder.URI : null;
  304.  
  305.     if (window.arguments[2])
  306.       originalView = window.arguments[2];
  307.  
  308.   }
  309.  
  310.   CreateView(originalView);
  311.  
  312.   setTimeout(OnLoadMessageWindowDelayed, 0, loadCustomMessage);
  313.  
  314.   SetupCommandUpdateHandlers();
  315. }
  316.  
  317. function OnLoadMessageWindowDelayed(loadCustomMessage)
  318. {
  319.   gDBView.suppressMsgDisplay = false;
  320.   if (loadCustomMessage)
  321.     gDBView.loadMessageByUrl(gCurrentMessageUri);
  322.   else
  323.   {
  324.     var msgKey = extractMsgKeyFromURI(gCurrentMessageUri);
  325.     LoadMessageByViewIndex(gDBView.findIndexFromKey(msgKey, true));
  326.   }
  327.   gNextMessageViewIndexAfterDelete = gDBView.msgToSelectAfterDelete; 
  328.   UpdateStandAloneMessageCounts();
  329.    
  330.   // set focus to the message pane
  331.   window.content.focus();
  332.  
  333.   // since we just changed the pane with focus we need to update the toolbar to reflect this
  334.   // XXX TODO
  335.   // can we optimize
  336.   // and just update cmd_delete and button_delete?
  337.   UpdateMailToolbar("focus");
  338. }
  339.  
  340. function CreateView(originalView)
  341. {
  342.   var msgFolder = GetLoadedMsgFolder();
  343.  
  344.   // extract the sort type, the sort order, 
  345.   var sortType;
  346.   var sortOrder;
  347.   var viewFlags;
  348.   var viewType;
  349.  
  350.   if (originalView)
  351.   {
  352.     viewType = originalView.viewType;
  353.     viewFlags = originalView.viewFlags;
  354.     sortType = originalView.sortType;
  355.     sortOrder = originalView.sortOrder;
  356.   }
  357.   else if (msgFolder)
  358.   {
  359.     var msgDatabase = msgFolder.getMsgDatabase(msgWindow);
  360.     if (msgDatabase)
  361.     {
  362.       var dbFolderInfo = msgDatabase.dBFolderInfo;
  363.       sortType = dbFolderInfo.sortType;
  364.       sortOrder = dbFolderInfo.sortOrder;
  365.       viewFlags = dbFolderInfo.viewFlags;
  366.       viewType = dbFolderInfo.viewType;
  367.       msgDatabase = null;
  368.       dbFolderInfo = null;
  369.    }
  370.   }
  371.   else
  372.   {
  373.     viewType = nsMsgViewType.eShowSearch;
  374.   }
  375.  
  376.   // create a db view
  377.   CreateBareDBView(originalView, msgFolder, viewType, viewFlags, sortType, sortOrder); 
  378.  
  379.   var uri;
  380.   if (gCurrentMessageUri)
  381.     uri = gCurrentMessageUri;
  382.   else if (gCurrentFolderUri)
  383.     uri = gCurrentFolderUri;
  384.   else
  385.     uri = null;
  386.  
  387.   SetUpToolbarButtons(uri);
  388.  
  389.   // hook for extra toolbar items
  390.   var observerService = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);
  391.   observerService.notifyObservers(window, "mail:setupToolbarItems", uri);
  392. }
  393.  
  394. function extractMsgKeyFromURI()
  395. {
  396.   var msgKey = -1;
  397.   var msgHdr = messenger.msgHdrFromURI(gCurrentMessageUri);
  398.   if (msgHdr)
  399.     msgKey = msgHdr.messageKey;
  400.   return msgKey;
  401. }
  402.  
  403. function OnUnloadMessageWindow()
  404. {
  405.   RemoveToolBarPrefListener();
  406.     // FIX ME - later we will be able to use onunload from the overlay
  407.     OnUnloadMsgHeaderPane();
  408.  
  409.     OnMailWindowUnload();
  410. }
  411.  
  412. function CreateMessageWindowGlobals()
  413. {
  414.     gCompositeDataSource = Components.classes[compositeDataSourceContractID].createInstance();
  415.     gCompositeDataSource = gCompositeDataSource.QueryInterface(Components.interfaces.nsIRDFCompositeDataSource);
  416. }
  417.  
  418. function InitializeDataSources()
  419. {
  420.   AddDataSources();
  421.   //Now add datasources to composite datasource
  422.   gCompositeDataSource.AddDataSource(accountManagerDataSource);
  423.   gCompositeDataSource.AddDataSource(folderDataSource);
  424. }
  425.  
  426. function GetSelectedMsgFolders()
  427. {
  428.     var folderArray = new Array(1);
  429.     var msgFolder = GetLoadedMsgFolder();
  430.     if (msgFolder)
  431.         folderArray[0] = msgFolder;    
  432.  
  433.     return folderArray;
  434. }
  435.  
  436. function GetFirstSelectedMessage()
  437. {
  438.     return GetLoadedMessage();
  439. }
  440.  
  441. function GetNumSelectedMessages()
  442. {
  443.   return (gCurrentMessageUri) ? 1 : 0;
  444. }
  445.  
  446. function GetSelectedMessages()
  447. {
  448.     var messageArray = new Array(1);
  449.     var message = GetLoadedMessage();
  450.     if (message)
  451.         messageArray[0] = message;    
  452.  
  453.     return messageArray;
  454. }
  455.  
  456. function GetSelectedIndices(dbView)
  457. {
  458.   try {
  459.     var indicesArray = {}; 
  460.     var length = {};
  461.     dbView.getIndicesForSelection(indicesArray,length);
  462.     return indicesArray.value;
  463.   }
  464.   catch (ex) {
  465.     dump("ex = " + ex + "\n");
  466.     return null;
  467.   }
  468. }
  469.  
  470. function GetLoadedMsgFolder()
  471. {
  472.     if (gCurrentFolderUri)
  473.         return RDF.GetResource(gCurrentFolderUri).QueryInterface(Components.interfaces.nsIMsgFolder);
  474.     else
  475.     return null;
  476. }
  477.  
  478. function GetSelectedFolderURI()
  479. {
  480.   return gCurrentFolderUri;
  481. }
  482.  
  483. function GetLoadedMessage()
  484. {
  485.   return gCurrentMessageUri;
  486. }
  487.  
  488. //Clear everything related to the current message. called after load start page.
  489. function ClearMessageSelection()
  490. {
  491.     gCurrentMessageUri = null;
  492.     gCurrentFolderUri = null;
  493.   UpdateMailToolbar("clear msg, std alone window");
  494. }
  495.  
  496. function GetCompositeDataSource(command)
  497. {
  498.     return gCompositeDataSource;    
  499. }
  500.  
  501. function SetNextMessageAfterDelete()
  502. {
  503.   gNextMessageViewIndexAfterDelete = gDBView.msgToSelectAfterDelete;
  504. }
  505.  
  506. function SelectFolder(folderUri)
  507. {
  508.   if (folderUri == gCurrentFolderUri)
  509.     return;
  510.  
  511.   var msgfolder = RDF.GetResource(folderUri).QueryInterface(Components.interfaces.nsIMsgFolder);
  512.   if (!msgfolder || msgfolder.isServer)
  513.     return;
  514.  
  515.   // close old folder view
  516.   var dbview = GetDBView();  
  517.   if (dbview)
  518.     dbview.close(); 
  519.  
  520.   gCurrentFolderToRerootForStandAlone = folderUri;
  521.  
  522.   if (msgfolder.manyHeadersToDownload)
  523.   {
  524.     gRerootOnFolderLoadForStandAlone = true;
  525.     try
  526.     {
  527.       msgfolder.startFolderLoading();
  528.       msgfolder.updateFolder(msgWindow);
  529.     }
  530.     catch(ex)
  531.     {
  532.       dump("Error loading with many headers to download: " + ex + "\n");
  533.     }
  534.   }
  535.   else
  536.   {
  537.     RerootFolderForStandAlone(folderUri);
  538.     gRerootOnFolderLoadForStandAlone = false;
  539.     msgfolder.startFolderLoading();
  540.  
  541.     //Need to do this after rerooting folder.  Otherwise possibility of receiving folder loaded
  542.     //notification before folder has actually changed.
  543.     msgfolder.updateFolder(msgWindow);
  544.   }    
  545. }
  546.  
  547. function RerootFolderForStandAlone(uri)
  548. {
  549.   gCurrentFolderUri = uri;
  550.  
  551.   // create new folder view
  552.   CreateView(null);
  553.   
  554.   // now do the work to load the appropriate message
  555.   if (gNextMessageAfterLoad) {
  556.     var type = gNextMessageAfterLoad;
  557.     gNextMessageAfterLoad = null;
  558.     LoadMessageByNavigationType(type);
  559.   }
  560.   
  561.   SetUpToolbarButtons(gCurrentFolderUri);
  562.   
  563.   UpdateMailToolbar("reroot folder in stand alone window");
  564.   
  565.   // hook for extra toolbar items
  566.   var observerService = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);
  567.   observerService.notifyObservers(window, "mail:setupToolbarItems", uri);
  568.  
  569. function GetMsgHdrFromUri(messageUri)
  570. {
  571.   return messenger.msgHdrFromURI(messageUri);
  572. }
  573.  
  574. function SelectMessage(messageUri)
  575. {
  576.   var msgHdr = GetMsgHdrFromUri(messageUri);
  577.   LoadMessageByMsgKey(msgHdr.messageKey);
  578. }
  579.  
  580. function ReloadMessage()
  581. {
  582.   gDBView.reloadMessage();
  583. }
  584.  
  585. function MsgDeleteMessageFromMessageWindow(reallyDelete, fromToolbar)
  586. {
  587.   // if from the toolbar, return right away if this is a news message
  588.   // only allow cancel from the menu:  "Edit | Cancel / Delete Message"
  589.   if (fromToolbar)
  590.   {
  591.     if (isNewsURI(gCurrentFolderUri)) 
  592.     {
  593.         // if news, don't delete
  594.         return;
  595.     }
  596.   }
  597.   
  598.   // before we delete 
  599.   SetNextMessageAfterDelete();
  600.  
  601.   if (reallyDelete)
  602.       gDBView.doCommand(nsMsgViewCommandType.deleteNoTrash);
  603.   else
  604.       gDBView.doCommand(nsMsgViewCommandType.deleteMsg);
  605. }
  606.  
  607. // MessageWindowController object (handles commands when one of the trees does not have focus)
  608. var MessageWindowController =
  609. {
  610.   supportsCommand: function(command)
  611.   {
  612.     switch (command)
  613.     {
  614.       case "cmd_delete":
  615.       case "cmd_undo":
  616.       case "cmd_redo":
  617.       case "cmd_killThread":
  618.       case "cmd_watchThread":
  619.       case "button_delete":
  620.       case "button_junk":
  621.       case "cmd_shiftDelete":
  622.       case "cmd_saveAsFile":
  623.       case "cmd_saveAsTemplate":
  624.       case "cmd_viewPageSource":
  625.       case "cmd_getMsgsForAuthAccounts":
  626.       case "button_mark":
  627.       case "cmd_markAsRead":
  628.       case "cmd_markAllRead":
  629.       case "cmd_markThreadAsRead":
  630.       case "cmd_markReadByDate":
  631.       case "cmd_markAsFlagged":
  632.       case "cmd_label0":
  633.       case "cmd_label1":
  634.       case "cmd_label2":
  635.       case "cmd_label3":
  636.       case "cmd_label4":
  637.       case "cmd_label5":
  638.       case "button_file":
  639.       case "cmd_file":
  640.       case "cmd_markAsJunk":
  641.       case "cmd_markAsNotJunk":
  642.       case "cmd_recalculateJunkScore":
  643.       case "cmd_markAsShowRemote":
  644.       case "cmd_markAsNotPhish":
  645.       case "cmd_applyFilters":
  646.       case "cmd_runJunkControls":
  647.       case "cmd_deleteJunk":
  648.       case "cmd_nextMsg":
  649.       case "button_next": 
  650.       case "cmd_nextUnreadMsg": 
  651.       case "cmd_nextFlaggedMsg": 
  652.       case "cmd_nextUnreadThread": 
  653.       case "cmd_previousMsg": 
  654.       case "cmd_previousUnreadMsg": 
  655.       case "cmd_previousFlaggedMsg":
  656.         return (gDBView.keyForFirstSelectedMessage != nsMsgKey_None);
  657.       case "cmd_reply":
  658.       case "button_reply":
  659.       case "cmd_replySender":
  660.       case "cmd_replyGroup":
  661.       case "cmd_replyall":
  662.       case "button_replyall":
  663.       case "cmd_forward":
  664.       case "button_forward":
  665.       case "cmd_forwardInline":
  666.       case "cmd_forwardAttachment":
  667.       case "cmd_editAsNew":
  668.       case "cmd_getNextNMessages":
  669.       case "cmd_find":
  670.       case "cmd_findAgain":
  671.       case "cmd_findPrev":
  672.       case "cmd_search":
  673.       case "cmd_reload":
  674.       case "cmd_getNewMessages":
  675.       case "button_getNewMessages":
  676.       case "button_print":
  677.       case "cmd_print":
  678.       case "cmd_printpreview":
  679.       case "cmd_printSetup":
  680.       case "cmd_close":
  681.       case "cmd_settingsOffline":
  682.       case "cmd_createFilterFromPopup":
  683.       case "cmd_createFilterFromMenu":
  684.         return true;
  685.       case "cmd_synchronizeOffline":
  686.       case "cmd_downloadFlagged":
  687.       case "cmd_downloadSelected":
  688.         return CheckOnline();
  689.       default:
  690.         return false;
  691.     }
  692.   },
  693.  
  694.     isCommandEnabled: function(command)
  695.     {
  696.     var loadedFolder;
  697.  
  698.         switch (command)
  699.         {
  700.       case "cmd_createFilterFromPopup":
  701.       case "cmd_createFilterFromMenu":
  702.         loadedFolder = GetLoadedMsgFolder();
  703.         return (loadedFolder && loadedFolder.server.canHaveFilters);
  704.             case "cmd_delete":
  705.         UpdateDeleteCommand();
  706.         // fall through
  707.             case "button_delete":
  708.             case "cmd_shiftDelete":
  709.         loadedFolder = GetLoadedMsgFolder();
  710.         return gCurrentMessageUri && loadedFolder && (loadedFolder.canDeleteMessages || isNewsURI(gCurrentFolderUri));
  711.       case "button_junk":
  712.         UpdateJunkToolbarButton();
  713.         // fall through
  714.       case "cmd_markAsJunk":
  715.             case "cmd_markAsNotJunk":
  716.       case "cmd_recalculateJunkScore":
  717.         // can't do junk on news yet
  718.         return (!isNewsURI(gCurrentFolderUri));
  719.             case "cmd_reply":
  720.             case "button_reply":
  721.             case "cmd_replySender":
  722.             case "cmd_replyGroup":
  723.             case "cmd_replyall":
  724.             case "button_replyall":
  725.             case "cmd_forward":
  726.             case "button_forward":
  727.             case "cmd_forwardInline":
  728.             case "cmd_forwardAttachment":
  729.             case "cmd_editAsNew":
  730.             case "cmd_print":
  731.             case "cmd_printpreview":
  732.       case "button_print":
  733.             case "cmd_saveAsFile":
  734.             case "cmd_saveAsTemplate":
  735.             case "cmd_viewPageSource":
  736.             case "cmd_reload":
  737.             case "cmd_find":
  738.       case "button_mark":
  739.             case "cmd_markAsRead":
  740.             case "cmd_markAllRead":
  741.             case "cmd_markThreadAsRead":
  742.             case "cmd_markReadByDate":
  743.       case "cmd_label0":
  744.       case "cmd_label1":
  745.       case "cmd_label2":
  746.       case "cmd_label3":
  747.       case "cmd_label4":
  748.       case "cmd_label5":
  749.         return true;
  750.             case "cmd_markAsFlagged":
  751.       case "button_file":
  752.             case "cmd_file":
  753.         return (gCurrentMessageUri != null);
  754.       case "cmd_markAsShowRemote":
  755.         return (GetNumSelectedMessages() > 0 && checkMsgHdrPropertyIsNot("remoteContentPolicy", kAllowRemoteContent));
  756.       case "cmd_markAsNotPhish":
  757.         return (GetNumSelectedMessages() > 0 && checkMsgHdrPropertyIsNot("notAPhishMessage", kNotAPhishMessage));
  758.             case "cmd_printSetup":
  759.               return true;
  760.             case "cmd_getNewMessages":
  761.       case "button_getNewMessages":
  762.       case "cmd_getMsgsForAuthAccounts":
  763.                 return IsGetNewMessagesEnabled();
  764.             case "cmd_getNextNMessages":
  765.                 return IsGetNextNMessagesEnabled();        
  766.             case "cmd_downloadFlagged":
  767.             case "cmd_downloadSelected":
  768.       case "cmd_synchronizeOffline":
  769.                 return CheckOnline();
  770.             case "cmd_settingsOffline":
  771.                 return IsAccountOfflineEnabled();
  772.             case "cmd_close":
  773.             case "cmd_nextMsg":
  774.       case "button_next":
  775.             case "cmd_nextUnreadMsg":
  776.             case "cmd_nextUnreadThread":
  777.             case "cmd_previousMsg":
  778.             case "cmd_previousUnreadMsg":
  779.                 return true;
  780.             case "cmd_findAgain":
  781.             case "cmd_findPrev":
  782.                 return MsgCanFindAgain();
  783.       case "cmd_search":
  784.         loadedFolder = GetLoadedMsgFolder();
  785.         return (loadedFolder && loadedFolder.server.canSearchMessages);
  786.       case "cmd_undo":
  787.       case "cmd_redo":
  788.         return SetupUndoRedoCommand(command);
  789.       case "cmd_applyFilters":
  790.       case "cmd_runJunkControls":
  791.       case "cmd_deleteJunk":
  792.         return false;
  793.             default:
  794.                 return false;
  795.         }
  796.     },
  797.  
  798.     doCommand: function(command)
  799.     {
  800.     // if the user invoked a key short cut then it is possible that we got here for a command which is
  801.     // really disabled. kick out if the command should be disabled.
  802.     if (!this.isCommandEnabled(command)) return;
  803.  
  804.     var navigationType = nsMsgNavigationType.nextUnreadMessage;
  805.  
  806.         switch ( command )
  807.         {
  808.             case "cmd_close":
  809.                 CloseMailWindow();
  810.                 break;
  811.             case "cmd_getNewMessages":
  812.                 MsgGetMessage();
  813.                 break;
  814.             case "cmd_undo":
  815.                 messenger.Undo(msgWindow);
  816.                 break;
  817.             case "cmd_redo":
  818.                 messenger.Redo(msgWindow);
  819.                 break;
  820.       case "cmd_getMsgsForAuthAccounts":
  821.         MsgGetMessagesForAllAuthenticatedAccounts();
  822.         break;
  823.             case "cmd_getNextNMessages":
  824.                 MsgGetNextNMessages();
  825.                 break;
  826.             case "cmd_reply":
  827.                 MsgReplyMessage(null);
  828.                 break;
  829.             case "cmd_replySender":
  830.                 MsgReplySender(null);
  831.                 break;
  832.             case "cmd_replyGroup":
  833.                 MsgReplyGroup(null);
  834.                 break;
  835.             case "cmd_replyall":
  836.                 MsgReplyToAllMessage(null);
  837.                 break;
  838.             case "cmd_forward":
  839.                 MsgForwardMessage(null);
  840.                 break;
  841.             case "cmd_forwardInline":
  842.                 MsgForwardAsInline(null);
  843.                 break;
  844.             case "cmd_forwardAttachment":
  845.                 MsgForwardAsAttachment(null);
  846.                 break;
  847.             case "cmd_editAsNew":
  848.                 MsgEditMessageAsNew();
  849.                 break;
  850.       case "cmd_createFilterFromPopup":
  851.         CreateFilter(document.popupNode);
  852.         break;
  853.       case "cmd_createFilterFromMenu":
  854.         MsgCreateFilter();
  855.                 break;        
  856.             case "cmd_delete":
  857.                 MsgDeleteMessageFromMessageWindow(false, false);
  858.                 break;
  859.             case "cmd_shiftDelete":
  860.                 MsgDeleteMessageFromMessageWindow(true, false);
  861.                 break;
  862.       case "button_junk":
  863.         MsgJunk();
  864.         break;
  865.             case "button_delete":
  866.                 MsgDeleteMessageFromMessageWindow(false, true);
  867.                 break;
  868.           case "cmd_printSetup":
  869.             NSPrintSetup();
  870.             break;
  871.             case "cmd_print":
  872.                 PrintEnginePrint();
  873.                 break;
  874.             case "cmd_printpreview":
  875.                 PrintEnginePrintPreview();
  876.                 break;
  877.             case "cmd_saveAsFile":
  878.                 MsgSaveAsFile();
  879.                 break;
  880.             case "cmd_saveAsTemplate":
  881.                 MsgSaveAsTemplate();
  882.                 break;
  883.             case "cmd_viewPageSource":
  884.                 MsgViewPageSource();
  885.                 break;
  886.             case "cmd_reload":
  887.                 MsgReload();
  888.                 break;
  889.             case "cmd_find":
  890.                 MsgFind();
  891.                 break;
  892.             case "cmd_findAgain":
  893.                 MsgFindAgain(false);
  894.                 break;
  895.             case "cmd_findPrev":
  896.                 MsgFindAgain(true);
  897.                 break;
  898.       case "cmd_search":
  899.         MsgSearchMessages();
  900.         break;
  901.       case "button_mark":
  902.             case "cmd_markAsRead":
  903.                 MsgMarkMsgAsRead(null);
  904.                 return;
  905.             case "cmd_markThreadAsRead":
  906.                 MsgMarkThreadAsRead();
  907.                 return;
  908.             case "cmd_markAllRead":
  909.                 MsgMarkAllRead();
  910.                 return;
  911.             case "cmd_markReadByDate":
  912.                 MsgMarkReadByDate();
  913.                 return;
  914.             case "cmd_markAsFlagged":
  915.                 MsgMarkAsFlagged(null);
  916.                 return;
  917.             case "cmd_markAsJunk":
  918.         JunkSelectedMessages(true);
  919.                 return;
  920.             case "cmd_markAsNotJunk":
  921.         JunkSelectedMessages(false);
  922.                 return;
  923.       case "cmd_recalculateJunkScore":
  924.         analyzeMessagesForJunk();
  925.         return;
  926.       case "cmd_markAsShowRemote":
  927.         LoadMsgWithRemoteContent();
  928.         return;
  929.       case "cmd_markAsNotPhish":
  930.         MsgIsNotAScam();
  931.         return;
  932.       case "cmd_label0":
  933.         gDBView.doCommand(nsMsgViewCommandType.label0);
  934.                  return;
  935.       case "cmd_label1":
  936.         gDBView.doCommand(nsMsgViewCommandType.label1);
  937.         return; 
  938.       case "cmd_label2":
  939.         gDBView.doCommand(nsMsgViewCommandType.label2);
  940.         return; 
  941.       case "cmd_label3":
  942.         gDBView.doCommand(nsMsgViewCommandType.label3);
  943.         return; 
  944.       case "cmd_label4":
  945.         gDBView.doCommand(nsMsgViewCommandType.label4);
  946.         return; 
  947.       case "cmd_label5":
  948.         gDBView.doCommand(nsMsgViewCommandType.label5);
  949.         return; 
  950.       case "cmd_downloadFlagged":
  951.         MsgDownloadFlagged();
  952.         return;
  953.       case "cmd_downloadSelected":
  954.         MsgDownloadSelected();
  955.         return;
  956.       case "cmd_synchronizeOffline":
  957.         MsgSynchronizeOffline();
  958.         return;
  959.       case "cmd_settingsOffline":
  960.         MsgSettingsOffline();
  961.         return;
  962.       case "cmd_nextUnreadMsg":
  963.       case "button_next":
  964.         performNavigation(nsMsgNavigationType.nextUnreadMessage);
  965.         break;
  966.             case "cmd_nextUnreadThread":      
  967.         performNavigation(nsMsgNavigationType.nextUnreadThread);
  968.                 break;
  969.             case "cmd_nextMsg":
  970.         performNavigation(nsMsgNavigationType.nextMessage);
  971.                 break;
  972.             case "cmd_nextFlaggedMsg":
  973.         performNavigation(nsMsgNavigationType.nextFlagged);
  974.                 break;
  975.             case "cmd_previousMsg":
  976.         performNavigation(nsMsgNavigationType.previousMessage);
  977.                 break;
  978.             case "cmd_previousUnreadMsg":
  979.         performNavigation(nsMsgNavigationType.previousUnreadMessage);
  980.                 break;
  981.             case "cmd_previousFlaggedMsg":
  982.         performNavigation(nsMsgNavigationType.previousFlagged);
  983.                 break;
  984.         }
  985.     },
  986.     
  987.     onEvent: function(event)
  988.     {
  989.     }
  990. };
  991.  
  992. function LoadMessageByNavigationType(type)
  993. {
  994.   var resultId = new Object;
  995.   var resultIndex = new Object;
  996.   var threadIndex = new Object;
  997.  
  998.   gDBView.viewNavigate(type, resultId, resultIndex, threadIndex, true /* wrap */);
  999.  
  1000.   // if we found something....display it.
  1001.   if ((resultId.value != nsMsgKey_None) && (resultIndex.value != nsMsgKey_None)) 
  1002.   {
  1003.     // load the message key
  1004.     LoadMessageByMsgKey(resultId.value);
  1005.     // if we changed folders, the message counts changed.
  1006.     UpdateStandAloneMessageCounts();
  1007.  
  1008.     // new message has been loaded
  1009.     return true;
  1010.   }
  1011.  
  1012.   // no message found to load
  1013.   return false;
  1014. }
  1015.    
  1016. function performNavigation(type)
  1017. {
  1018.   // Try to load a message by navigation type if we can find
  1019.   // the message in the same folder.
  1020.   if (LoadMessageByNavigationType(type))
  1021.     return;
  1022.    
  1023.   CrossFolderNavigation(type);
  1024. }
  1025.  
  1026. function SetupCommandUpdateHandlers()
  1027. {
  1028.     top.controllers.insertControllerAt(0, MessageWindowController);
  1029. }
  1030.  
  1031. function GetDBView()
  1032. {
  1033.   return gDBView;
  1034. }
  1035.  
  1036. function LoadMessageByMsgKey(messageKey)
  1037. {
  1038.   var viewIndex = gDBView.findIndexFromKey(messageKey, true);
  1039.   gDBView.loadMessageByViewIndex(viewIndex);
  1040.  // we only want to update the toolbar if there was no previous selected message.
  1041.   if (nsMsgKey_None == gDBView.keyForFirstSelectedMessage)
  1042.     UpdateMailToolbar("update toolbar for message Window");
  1043. }
  1044.  
  1045. function LoadMessageByViewIndex(viewIndex)
  1046. {
  1047.   gDBView.loadMessageByViewIndex(viewIndex);
  1048.   // we only want to update the toolbar if there was no previous selected message.
  1049.   if (nsMsgKey_None == gDBView.keyForFirstSelectedMessage)
  1050.     UpdateMailToolbar("update toolbar for message Window");
  1051. }
  1052.